
#include "Debug.h"
#include "simple_protocol.h"
#include "utility.h"
#include <phNfcLib_Int.h>
#include <phNfcLib_Initialization.h>
#include <Reader/Reader.h>


enum {
	API_15693_GENERICCOMMAND = 0,
	API_15693_GETSYSTEMINFORMATION = 1,
	API_15693_GETSYSTEMINFORMATIONEXT = 2,
	API_15693_GETTAGTYPEFROMUID = 3,
	API_15693_GETTAGTYPEFROMSYSTEMINFO = 4,
	API_15693_READSINGLEBLOCK = 5,
	API_15693_READSINGLEBLOCKEXT = 6,
	API_15693_WRITESINGLEBLOCK = 7,
	API_15693_WRITESINGLEBLOCKEXT = 8,
	API_15693_NUM,
};


phStatus_t Iso15693_SingleRead(uint8_t block, uint8_t ** ppData, uint16_t * pDataLen){
	void *psal15693 = phNfcLib_GetDataParams(PH_COMP_AL_ICODE);
	return phalICode_ReadSingleBlock(psal15693, PHAL_ICODE_OPTION_OFF, block, ppData, pDataLen);
}

phStatus_t Iso15693_SingleWrite(uint8_t block, uint8_t* Data, uint8_t len){
	void *psal15693 = phNfcLib_GetDataParams(PH_COMP_AL_ICODE);
	return phalICode_WriteSingleBlock(psal15693, PHAL_ICODE_OPTION_OFF, block, Data, len);
}

#if 0
static int api_ISO15693_GetSystemInfomation(buffer_t* command, buffer_t* response){		//测试和Elatec 数据不一致
	void *psalicode = phNfcLib_GetDataParams(PH_COMP_AL_ICODE);
	uint8_t* rdata = NULL;
	uint16_t rlen = 0;
	phStatus_t status = phalICode_Sw_GetSystemInformation(psalicode, &rdata, &rlen);
	uint8_t result = status ? 0 : 1;
	net_buf_simple_push_u8(response, result);
	if(result){
		net_buf_simple_add_mem(response, rdata, rlen);
	}
	
	return ERR_NONE;
}
#endif
// static int api_ISO15693_gen_command(buffer_t* command, buffer_t* response)
// {
// #pragma pack(1)
// 	typedef struct{
// 		uint8_t flags;
// 		uint8_t command;
// 		uint8_t data[];		
// 	}gen_command_param_t;
// #pragma pack()
	
// 	gen_command_param_t* gen_param = (gen_command_param_t*) command->data;
// 	uint16_t rx_len = 0;
// 	uint8_t* data = NULL;
// 	uint8_t* rdata = NULL;
// 	uint16_t rlen = 0;
// 	phpalSli15693_Sw_DataParams_t *psal15693 = (phpalSli15693_Sw_DataParams_t*)phNfcLib_GetDataParams(PH_COMP_PAL_SLI15693);
// 	phStatus_t  wStatus = 0;
// 	// PH_CHECK_SUCCESS_FCT(wStatus, phpalSli15693_SetConfig(
// 	// 	psal15693,
// 	// 	PHPAL_SLI15693_CONFIG_FLAGS,
// 	// 	gen_param->flags));
// 	/* Set long timeout. */
// 	// wStatus = phpalSli15693_Sw_ResetToReady(psal15693);
// 	PH_CHECK_SUCCESS_FCT(wStatus, phpalSli15693_SetConfig(
// 			psal15693,
// 			PHPAL_SLI15693_CONFIG_TIMEOUT_US,
// 			PHPAL_SLI15693_TIMEOUT_LONG_US));
// 	uint8_t cbuf[16];
// 	cbuf[0] = gen_param->command;
// 	memcpy(cbuf+1, gen_param->data+1, gen_param->data[0]);
// 	// uint8_t clen = gen_param->data[0] + 1;
// 	uint8_t clen = 1;
//     wStatus = phpalSli15693_Exchange(
//             psal15693,
//             PH_EXCHANGE_DEFAULT,
//             cbuf,
//             clen,
//             &rdata,
//             &rlen);
	
// 	uint8_t result = wStatus ? 0 : 1;
// 	net_buf_simple_push_u8(response, result);
// 	if(result){
// 		net_buf_simple_add_mem(response, rdata, rlen);
// 	}
	
// 	return ERR_NONE;
// }



static int api_ISO15693_ReadSingleBlock(buffer_t* command, buffer_t* response)
{
#pragma pack(1)
	typedef struct{
		uint16_t blocknum;
		uint8_t buffersize;
	}readblock_param_t;
#pragma pack()
	
	readblock_param_t* read_param = (readblock_param_t*) command->data;
	uint16_t rx_len = 0;
	uint8_t* data = NULL;
	phStatus_t status = Iso15693_SingleRead(read_param->blocknum, &data, &rx_len);
	uint8_t result = status ? 0 : 1;
	net_buf_simple_push_u8(response, result);
	if(result){
		if(rx_len > read_param->buffersize){
			rx_len = read_param->buffersize;
		}
		net_buf_simple_add_u8(response, rx_len);
		net_buf_simple_add_mem(response, data, rx_len);
	}

	return ERR_NONE;
}

typedef struct {
	uint16_t blocknum;
	uint8_t wlen;
	uint8_t *Data;
}ISO15693WriteSingle_param_t;

static void get_command_param_ISO15693_WriteSingle(buffer_t* command, ISO15693WriteSingle_param_t* param){	
	param->blocknum = net_buf_simple_pull_le16(command);
	param->wlen = net_buf_simple_pull_u8(command);
	param->Data = net_buf_simple_pull_mem(command, param->wlen);
}

static int api_ISO15693_WriteSingleBlock(buffer_t* command, buffer_t* response)
{
	ISO15693WriteSingle_param_t param;
	get_command_param_ISO15693_WriteSingle(command, &param);

	phStatus_t status = Iso15693_SingleWrite(param.blocknum, param.Data, param.wlen);
	uint8_t result = status ? 0 : 1;
	net_buf_simple_push_u8(response, result);

	return ERR_NONE;
}

static const api_entry_t api_15693_list[API_15693_NUM] = {
	[API_15693_GENERICCOMMAND] = NULL,
	[API_15693_GETSYSTEMINFORMATION] = NULL,
	[API_15693_GETSYSTEMINFORMATIONEXT] = NULL,
	[API_15693_GETTAGTYPEFROMUID] = NULL,
	[API_15693_GETTAGTYPEFROMSYSTEMINFO] = NULL,
	[API_15693_READSINGLEBLOCK] = api_ISO15693_ReadSingleBlock,
	[API_15693_READSINGLEBLOCKEXT] = NULL,
	[API_15693_WRITESINGLEBLOCK] = api_ISO15693_WriteSingleBlock,
	[API_15693_WRITESINGLEBLOCKEXT] = NULL,
};
	
static int iso15693_api(buffer_t* command, buffer_t* response){
	const uint8_t num = sizeof(api_15693_list)/sizeof(api_15693_list[0]);
	return protocol_call_api(api_15693_list, num, command, response);
}

SIMPLE_API_DEFINE(API_CLASS_15693, iso15693_api);



